#!/usr/bin/env bash

# PACKAGE: Gunther
# VERSION: 2.0
# DATE: 09/30/08
# AUTHOR(S): Zarrar Shehzad


# CONSTANTS FOR ERROR RETURNS
declare -r INPUT_ERROR=21
declare -r OUTPUT_ERROR=22


function xfcExecute_for {
    # User Variables
    local command="$1"
    local start="$2"
    local end="$3"
    # Function Variables
    local returnVal=0

    for (( i = ${start}; i <= ${end}; i++ )); do
        zcmd "$command"
        returnVal="$?"
        if [[ "$returnVal" -ne 0 ]]; then
            return "$returnVal"
        fi
    done
    
    return 0
}

function xfcExecute_for_info {
    # User Variables
    local command="$1"
    local start="$2"
    local end="$3"
    # Function Variables
    local returnVal=0

    for (( i = ${start}; i <= ${end}; i++ )); do
        zcmd_info "$command"
    done
    
    return 0
}

function xfcExecute_for_exec {
    # User Variables
    local command="$1"
    local start="$2"
    local end="$3"
    # Function Variables
    local returnVal=0

    for (( i = ${start}; i <= ${end}; i++ )); do
        zcmd_exec "$command"
        returnVal="$?"
        if [[ "$returnVal" -ne 0 ]]; then
            return "$returnVal"
        fi
    done
    
    return 0
}

function xfcExecute_if {
    # User Variables
    local commandsTrue="$1"
    local comparison="$2"
    local commandsFalse="$3"

    if [[ $(( ${comparison} )) = 1 ]]; then
        eval "$commandsTrue"
    else
        eval "$commandsFalse"
    fi
    
    return "$?"
}



# Info:
#   Will execute a given command (i.e., a wrapper function)
# Usage:
#   xfcExecute "<some command>" "<info (optional)>" "<input files (optional)>" "<output files (optional)"
# Options:
#   * command: a command to execute
#   * info: information to display before execution
#   * input: input files, will check if these exist
#   * output: output files, will check if these exist
#   * extension: can be a for loop and in the future an if statement (set as: "for") [optional]
#   * extension options: additional parameters for extension [optional]
# Return:
#   $INPUT_ERROR -> input file(s) don't exist
#   $OUTPUT_ERROR -> output file(s) exist and to_force=0 (i.e., don't overwrite)
#   0 -> ok
#   * -> non-zero exist from command
# Exit:
#   -2 -> no command given
# Notes:
#   * see checkInput and checkOutput for what happens to input and output files
#   * multiple input and output files can be seperated by space
#   * uses global variable $dry_run
function xfcExecute {
    # User given vars
    local command="$1"
    local info="$2"
    local inputs="$3"
    local outputs="$4"
    local ext="$5"
    
    # Other vars
    local input=""
    local output=""
    
    # INSANITY CHECK
    if [[ -z "$command" ]]; then
        zemerg "No command given...stopping program"
        exit -2
    fi
    
    # DOLE OUT INFORMATION
    if [[ ! -z "$info" ]]; then
        zinfo "$info"
    fi
    
    # ECHO COMMANDS (TO STD-OUT)
    case "$ext" in
        "for" )
            local start="$6"
            local end="$7"
            xfcExecute_for_info "$command" "$start" "$end"
            ;;
        * )
            zcmd_info "$command"
            ;;
    esac
    
    # CHECK FOR DRY RUN
    if [[ "$dry_run" = 1 ]]; then
        return 0
    fi
    
    # CHECK INPUT
    if [[ ! -z "$inputs" ]]; then
        checkInput "$inputs"
        if [[ "$?" -ne 0 ]]; then
            return $INPUT_ERROR
        fi
    fi
    
    # CHECK OUTPUT
    if [[ ! -z "$outputs" ]]; then
        checkOutput "$outputs"
        if [[ "$?" -ne 0 ]]; then
            return $OUTPUT_ERROR
        fi
    fi
    
    # EXECUTE (finally)
    case $ext in
        "if" )
            local comparison="$6"
            local commandsFalse="$7"
            xfcExecute_if "$comparison" "$command" "$commandsFalse"
            local returnVal="$?"
            ;;
        "for" )
            local start="$6"
            local end="$7"
            xfcExecute_for_exec "$command" "$start" "$end"
            local returnVal="$?"
            ;;
        * ) 
            zcmd_exec "$command"
            local returnVal="$?"
            ;;
        
    esac
    
    # Check return
    if [[ "$returnVal" -ne 0 ]]; then
        zerror "non-zero exit while executing '${command:0:25}.....'"
    fi
    return "$returnVal"
    
}
